/*
 * WH-GM5 4G模块
 */
#include "head\WHGM5.h"
#include "head\MCU.h"

void WHGM5_Init(uint8_t sock,uint8_t protocol,uint8_t *ipAdress,uint8_t *port)
{
    /*
     * 配置串口引脚
     */
    GPIO_setAsPeripheralModuleFunctionInputPin(
            WHGM5_USCI_PORT,
            WHGM5_USCI_PIN_TX + WHGM5_USCI_PIN_RX
        );

    /*
     * 配置串口
     */
    USCI_A_UART_initParam param = {0};
    param.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK; //选择SMCLK为时钟源
    if(MSP430_FREQUENCY == 25165824)
    {
        param.clockPrescalar = 218;//25,165,824/115200
        param.secondModReg = 4;
    }
    else if(MSP430_FREQUENCY == 16777216)
    {
        param.clockPrescalar = 145;//16,777,216/115200 ~= 145.63555
        param.secondModReg = 5;//0.63555 * 8 ~= 5.08444
    }
    param.firstModReg = 0; //这个是用在过采样波特率模式，公式见用户手册36.3.10.2
    param.parity = USCI_A_UART_NO_PARITY; //奇偶校验
    param.msborLsbFirst = USCI_A_UART_LSB_FIRST; //“控制移位寄存器的方向”，及大小端。LSB属于小端，高位字节放高端
    param.numberofStopBits = USCI_A_UART_ONE_STOP_BIT; //停止位数
    param.uartMode = USCI_A_UART_MODE; //普通串口模式
    param.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION; //低采样波特率或过采样波特率选择
    if (STATUS_FAIL == USCI_A_UART_init(WHGM5_USCI_BASE, &param)){
        return;
    }

    /*
     * 使能串口操作
     */
    USCI_A_UART_enable(WHGM5_USCI_BASE);//UCSWRST位置1

//    WHGM5_ClrStruct();

    /*
     * 使能串口中断
     */
    USCI_A_UART_clearInterrupt(WHGM5_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//标志位清除
    USCI_A_UART_enableInterrupt(WHGM5_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位

    WHGM5_ConfigModule(sock,protocol,ipAdress,port);
}

void WHGM5_ConfigModule(uint8_t sock,uint8_t protocol,uint8_t *ipAdress,uint8_t *port)
{
    uint8_t currentCount;
    uint8_t sockEn[14] = "AT+SOCKAEN=ON";

    /*
     * 进入配置模式
     */
    //发+++
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_sendStr("+++");
    WHGM5_waitRx(currentCount,30);
    //发a
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_sendStr("a");
    WHGM5_waitRx(currentCount,30);

    /*
     * 配置参数
     */
    //------------------设置TCPsever地址------------------
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
//    WHGM5_sendStr("AT+SOCKA=TCP,server.natappfree.cc,37686\r\n");
//    WHGM5_setSock('A',0,"server.natappfree.cc","37686");
    WHGM5_setSock(sock,protocol,ipAdress,port);
    WHGM5_waitRx(currentCount,30);

    //----------------------使能套接字----------------------
    if(sock!='A')//如果不是套接字A，则需要使能套接字
    {
        currentCount = WHGM5_RxBufferCount;
        WHGM5_RxBuffer[currentCount] = 0;
        sockEn[7] = sock;
        WHGM5_sendStr(sockEn);
        WHGM5_sendStr("\r\n");
        WHGM5_waitRx(currentCount,30);
    }
    //--------------------设置网络AT密码--------------------
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_sendStr("AT+CMDPW=PROG00\r\n");
    WHGM5_waitRx(currentCount,30);
    //--------------------关闭心跳包功能--------------------
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_sendStr("AT+HEARTEN=OFF\r\n");
    WHGM5_waitRx(currentCount,30);

    //重启保存
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_sendStr("AT+S\r\n");
    WHGM5_waitRx(currentCount,30);

    //等待重启成功
    currentCount = WHGM5_RxBufferCount;
    WHGM5_RxBuffer[currentCount] = 0;
    WHGM5_waitRx(currentCount,150);
    if(WHGM5_RxBuffer[currentCount] != 'W')
    {
        __no_operation();
    }
    memset(WHGM5_RxBuffer, 0, WHGM5_RxBuffer_Length);
    WHGM5_RxBufferCount=0;
}

//void WHGM5_ClrStruct()
//{
//    memset(WHGM5_RxBuffer, 0, WHGM5_RxBuffer_Length);
//    WHGM5_RxBufferCount=0;
//}

int8_t WHGM5_parse4GBuffer(uint8_t *RxCommand,uint8_t *RxParameter,uint8_t *RxParameterCount)
{
    uint8_t i;
    uint8_t index55;
    uint8_t index;
    uint8_t crc;
    uint8_t WHGM5_DataRxDataLen = 0;

    /*
     * 判断是否接到新数据
     */
    for(i=0;i<WHGM5_RxBuffer_Length;i++)
    {
        if(WHGM5_RxBuffer[i] == 0x55)//循环寻找0x55
        {
            uint8_t currentCount;
            index55 = i;
            WHGM5_RxBuffer[index55] = 0x00;
            index = WHGM5_getQueueIndex(index55+1);//定位0xcc的位置
            do{
                currentCount = WHGM5_RxBufferCount;
                __delay_cycles(MSP430_FREQUENCY/1000);//等待10ms
            }
            while(currentCount != WHGM5_RxBufferCount);
            if(WHGM5_RxBuffer[index] == 0xcc)//判断下一位是否是0xcc
            {
                //禁用中断
                USCI_A_UART_disableInterrupt(WHGM5_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);
                /*
                 * 取出长度信息
                 */
                index = WHGM5_getQueueIndex(index55+2);//定位lenLow的位置
                WHGM5_DataRxDataLen = WHGM5_RxBuffer[index];

                index = WHGM5_getQueueIndex(index55+3);//定位lenHigh的位置
                WHGM5_DataRxDataLen |= ((uint16_t)WHGM5_RxBuffer[index])<<8;
                break;
            }
        }
    }
    if(WHGM5_DataRxDataLen==0)
    {
        return 0;//没有新数据
    }

    /*
     * 计算校验和
     */
    crc = 0x55;
    for(i=1;i<WHGM5_DataRxDataLen-3;i++)
    {
        index = WHGM5_getQueueIndex(index55+i);//定位每一个数计算校验和
        crc += WHGM5_RxBuffer[index];
    }

    index = WHGM5_getQueueIndex(index55+WHGM5_DataRxDataLen-3);//定位校验和的位置
    if(WHGM5_RxBuffer[index]!=crc)
    {
        memset(WHGM5_RxBuffer, 0, WHGM5_RxBuffer_Length);
        WHGM5_RxBufferCount = 0;
        USCI_A_UART_enableInterrupt(WHGM5_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位
        return -1;//校验和不匹配
    }

    /*
     * 取出命令信息与参数信息
     */
    index = WHGM5_getQueueIndex(index55+4);//定位cmd的位置
    *RxCommand = WHGM5_RxBuffer[index];
    index = WHGM5_getQueueIndex(index55+5);//定位参数的位置
    memset(RxParameter, 0, WHGM5_RxParameter_Length);
    for(i=index;i<WHGM5_DataRxDataLen-3;i++)
    {
        RxParameter[i-index] = WHGM5_RxBuffer[i];
    }
    /*
     * 保存参数长度
     */
    *RxParameterCount = WHGM5_DataRxDataLen-8;

    /*
     * 该取出的数据都取完了，清空缓存
     */
    memset(WHGM5_RxBuffer, 0, WHGM5_RxBuffer_Length);
    WHGM5_RxBufferCount = 0;
    //使能中断
    USCI_A_UART_enableInterrupt(WHGM5_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位

    return 1;
}

uint8_t WHGM5_getQueueIndex(uint8_t index)
{
    if((index)<WHGM5_RxBuffer_Length){//判断往后数index位是否超出缓存
        return index;//未超出
    }else{
        return index-WHGM5_RxBuffer_Length;//超出
    }
}

void WHGM5_sendStr(uint8_t *str)
{
    for(;*str != '\0';str++)
    {
        USCI_A_UART_transmitData(WHGM5_USCI_BASE,*str);
    }
}

void WHGM5_sendStrLen(uint8_t *str,uint16_t len)
{
    uint16_t i;
    for(i=0;i<len;i++)
    {
        USCI_A_UART_transmitData(WHGM5_USCI_BASE,str[i]);
    }
}

void WHGM5_sendNum8(uint8_t num)
{
    uint8_t str[3]={0};
    uint8_t numDecimalLen;
    uint8_t i;
    uint8_t j;
    uint8_t pow = 1;
    //判断num是几位数
    for(i = 3;i > 0;i--)        //由于uint8_t最大为255，所以直接从3位数开始判断
    {
        uint8_t j;
        uint8_t pow = 1;
        for(j = i-1;j > 0;j--)  //得到10的i-1次幂
        {
            pow *= 10;
        }
        if(num / pow)           //拿10的i-1次幂相除取整，如果不为零，则num有i位数
        {
            numDecimalLen = i;
            break;
        }
    }
    if(numDecimalLen == 0)
    {
        uint8_t zero[2] = {0x30,0x00};
        WHGM5_sendStr(zero);
    }

    //单独取出每一位数字
    for(i = 0;i < numDecimalLen;i++)
    {
        pow = 1;
        for(j = numDecimalLen-i-1;j > 0;j--)  //得到10的i-1次幂
        {
            pow *= 10;
        }
        str[i] = num / pow; //取出十进制数第i位数字存在str
        num = num - (str[i] * pow); //将十进制第i位去除
        str[i] = (str[i]+0x30);     //将数字x转换成ascii码x
    }

    WHGM5_sendStr(str);
}

void WHGM5_sendNum16(uint16_t num)
{
    uint8_t str[5]={0};
    uint8_t numDecimalLen;
    uint8_t i;
    uint8_t j;
    uint16_t pow = 1;
    //判断num是几位数
    for(i = 5;i > 0;i--)        //由于uint16_t最大为65535，所以直接从5位数开始判断
    {
        pow = 1;
        for(j = i-1;j > 0;j--)  //得到10的i-1次幂
        {
            pow *= 10;
        }
        if(num / pow)           //拿10的i-1次幂相除取整，如果不为零，则num有i位数
        {
            numDecimalLen = i;
            break;
        }
    }
    if(numDecimalLen == 0)
    {
        uint8_t zero[2] = {0x30,0x30};
        WHGM5_sendStr(zero);
    }
    else
    {
        for(i = 0;i < numDecimalLen;i++)
        {
            pow = 1;
            for(j = numDecimalLen-i-1;j > 0;j--)  //得到10的i-1次幂
            {
                pow *= 10;
            }
            str[i] = (uint8_t)(num / pow); //取出十进制数第i位数字存在str
            num = num - (str[i] * pow); //将十进制第i位去除
            str[i] = (str[i]+0x30);     //将数字x转换成ascii码x
        }

        WHGM5_sendStr(str);
    }
}

int8_t WHGM5_waitRx(uint16_t currentCount, uint8_t Timeing)
{
    do{//等待返回数据，无论是'a'还是别的
        __delay_cycles(MSP430_FREQUENCY/10);
        Timeing--;
        if(Timeing == 0)
        {
            return -1;
        }
    }
    while(WHGM5_RxBuffer[currentCount] == 0);
    return 0;
}

//void WHGM5_powerON()
//{
//    GPIO_setOutputHighOnPin(WHGM5_POW_PORT,WHGM5_POW_PIN);
//}
//
//void WHGM5_powerOFF()
//{
//    GPIO_setOutputLowOnPin(WHGM5_POW_PORT,WHGM5_POW_PIN);
//}

void WHGM5_setSock(uint8_t sock,uint8_t protocol,uint8_t *ipAdress,uint8_t *port)
{
    uint8_t AT[13] = "AT+SOCKA=TCP";
    AT[7] = sock;
    if(protocol == 1)
    {
        AT[7] = 'U';
        AT[8] = 'D';
        AT[9] = 'P';
    }
    WHGM5_sendStr(AT);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,',');
    WHGM5_sendStr(ipAdress);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,',');
    WHGM5_sendStr(port);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,'\r');
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,'\n');

}

void WHGM5_sendHandshakeCmd(uint8_t *pmsp430_ID)
{
    uint16_t i;
    /*
     * 计算校验和
     */
    uint8_t crc=0x56;//0x55+0xcc+0x10+0x00+0x25 = 0x156
    for(i = 0;i < 8;i++)
    {
        crc += pmsp430_ID[i];
    }
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x55);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0xcc);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x10);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x00);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x25);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,pmsp430_ID[3]);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,pmsp430_ID[2]);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,pmsp430_ID[1]);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,pmsp430_ID[0]);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,crc);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x00);
    USCI_A_UART_transmitData(WHGM5_USCI_BASE,0x00);
}

//******************************************************************************
//
//This is the USCI_A0 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A1_VECTOR)))
#endif
void WHGM5_USCI_A1_ISR (void)
{
    switch (__even_in_range(UCA1IV,4)){
        case 2://Vector 2 - RXIFG
        {
            WHGM5_RxBuffer[WHGM5_RxBufferCount++] = USCI_A_UART_receiveData(WHGM5_USCI_BASE);
            if(WHGM5_RxBufferCount >= WHGM5_RxBuffer_Length)
            {
                WHGM5_RxBufferCount = 0;
            }
            break;
        }
        default: break;
    }
}

